package com.syjy.container;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;

import java.math.BigDecimal;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 协议采集到数据的容器
 *
 * @author 修唯xiuwei
 * @version 3.0
 */

@Slf4j
public class ProtocolDataContainer {


	/**
	 * 遥测数据
	 */
	private Map<Integer, BigDecimal> yc = new ConcurrentHashMap<>();
	/**
	 * 遥信数据
	 */
	private Map<Integer, Boolean> yx = new ConcurrentHashMap<>();
	/**
	 * 点位数据是否是有效值
	 */
	private Map<Integer, Boolean> isValid = new ConcurrentHashMap<>();


	private ProtocolDataContainer() {
	}

	/**
	 * 获取单例实例
	 *
	 * @return the instance
	 */
	public static final ProtocolDataContainer getInstance() {
		return LazyHolder.INSTANCE;
	}

	/**
	 * 向池子内置数据
	 *
	 * @param point point
	 * @param value value
	 */
	public void putNumber(Integer point, BigDecimal value) {
		this.yc.put(point, value);
	}


	/**
	 * 向池子内置数据
	 *
	 * @param point point
	 * @param value value
	 */
	public void putBoolean(Integer point, Boolean value) {
		this.yx.put(point, value);
	}


	/**
	 * 获取到缓存池内的数值 如果遥测池内没有但是存在于遥信池 将返回 0or1
	 *
	 * @param point 点位
	 * @return Number number
	 */
	public BigDecimal getNumber(Integer point) {
		if (isYcContains(point)) {
			return this.yc.get(point);
		} else if (isYxContains(point)) {
			return this.yx.get(point) ? BigDecimal.valueOf(1D) : BigDecimal.valueOf(0D);
		} else {
			return BigDecimal.valueOf(-99D);
		}
	}

	/**
	 * 获取到返回池内的遥信数据  如果遥信池内没有 遥测池内有 那么大于0的数值 将会返回ture 否则为false
	 *
	 * @param point 点位
	 * @return Boolean boolean
	 */
	public Boolean getBoolean(Integer point) {
		if (isYxContains(point)) {
			return this.yx.get(point);
		} else if (isYcContains(point)) {
			return this.yc.get(point).doubleValue() > 0;
		} else {
			return false;
		}
	}

	/**
	 * 获取所有的数值
	 *
	 * @return {@link Map<Integer, BigDecimal>}
	 */
	public  Map<Integer,BigDecimal>  getAllNumbers(){
		return this.yc;
	}

	/**
	 * 获取所有的遥信
	 *
	 * @return {@link Map<Integer, Boolean>}
	 */
	public  Map<Integer,Boolean>  getAllBooleans(){
		return this.yx;
	}

	/**
	 * 获取点位数据  直接返回
	 *
	 * @param point 点位key
	 * @return 返回值  可能是Boolean 或者是 BigDecimal
	 */
	public Object getData(Integer point) {
		if (isYcContains(point)) {
			return this.yc.get(point);
		}
		if (isYxContains(point)) {
			return this.yx.get(point);
		}
		return BigDecimal.valueOf(0);
	}

	/**
	 * 遥信数据池是否含有该点位
	 *
	 * @param point point
	 * @return the boolean
	 */
	public Boolean isYxContains(Integer point) {
		return this.yx.containsKey(point);
	}

	/**
	 * 遥测数据池是否含有该点位值
	 *
	 * @param point point
	 * @return the boolean
	 */
	public Boolean isYcContains(Integer point) {
		return this.yc.containsKey(point);
	}


	@Override
	public String toString() {
		JSONObject object = new JSONObject();
		object.put("yx", this.yx);
		object.put("yc", this.yc);
		return object.toJSONString();
	}

	/**
	 * 格式化打印信息 以表格的形式打印通道数据
	 *
	 * @return
	 */
	public String toStringFormatted() {
		StringBuffer stringBuffer = new StringBuffer();
		String splitLine = "—————————————————————|—————————————————————|——————————————————————\n";
		stringBuffer.append(DateTime.now().toString("yyyy-MM-dd HH:mm:ss:SSS") + "\n");
		stringBuffer.append(splitLine);
		stringBuffer.append("  key  |    value    |  key  |    value    |  key  |    value    |\n");
		stringBuffer.append(splitLine);
		int i = 0;
		Iterator<Integer> it = new TreeSet(this.yx.keySet()).iterator();
		Integer position;
		while (it.hasNext()) {
			position = it.next();
			stringBuffer.append(StringUtils.center(position + "", 7));
			stringBuffer.append("|");
			stringBuffer.append(StringUtils.center(this.yx.get(position) + "", 13));
			stringBuffer.append("|");
			i++;
			if (i % 3 == 0) {
				stringBuffer.append("\n");
				stringBuffer.append(splitLine);
			}
		}
		it = new TreeSet(this.yc.keySet()).iterator();
		while (it.hasNext()) {
			position = it.next();
			stringBuffer.append(StringUtils.center(position + "", 7));
			stringBuffer.append("|");
			stringBuffer.append(StringUtils.center(StringUtils.substring(this.yc.get(position) + "", 0, 11), 13));
			stringBuffer.append("|");
			i++;
			if (i % 3 == 0) {
				stringBuffer.append("\n");
				stringBuffer.append(splitLine);
			}
		}
		return stringBuffer.toString();
	}

	private static class LazyHolder {
		private static final ProtocolDataContainer INSTANCE = new ProtocolDataContainer();
	}

}
